/*
 * idCollector.h
 *
 *  Created on: Jan 20, 2010
 *      Author: kevin
 */

#ifndef IDCOLLECTOR_H_
#define IDCOLLECTOR_H_

#include <Poco/Thread.h>
using Poco::Thread;

#include <iostream>
using std::cout;
using std::endl;

#include <Poco/Runnable.h>
using Poco::Runnable;

#include <Poco/Types.h>
using Poco::UInt32;

#include <Poco/Timer.h>
using Poco::Timer;


#include <Poco/Semaphore.h>
using Poco::Semaphore;

#include <vector>
using std::vector;

#include <utility>
using std::pair;
#include <Poco/Net/Socket.h>
using Poco::Net::Socket;
#include <Poco/Net/DatagramSocket.h>
using Poco::Net::DatagramSocket;

#include <Poco/Net/MulticastSocket.h>
using Poco::Net::MulticastSocket;

#include <Poco/Net/SocketAddress.h>
using Poco::Net::SocketAddress;

#include <Poco/Types.h>
using Poco::UInt16;

class idCollector : public Runnable
{
	public:
		typedef Poco::UInt32 id_type;

		idCollector(UInt16 defport);
		virtual ~idCollector();

		id_type getId();
		id_type getPrevId();
		id_type getNextId();
		SocketAddress getPrevIP();
		SocketAddress getNextIP();

		Socket* getSocket(){
			cout << "IdCollector :: Getting my address " << endl;
			cout << "IdCollector :: Control :: " << _ds.address().toString() << endl;
			return &_ds;
		}

		UInt16 port();
		void run();
	private:
		typedef pair< SocketAddress, id_type > IDMapping;
		Timer* _timer;
		vector< IDMapping > _ids;
		id_type _id;
		Semaphore* _lock;
		bool _stopping;
		bool _isset;
		id_type _prev;
		SocketAddress _prevIp;
		id_type _next;
		SocketAddress _nextIp;
		DatagramSocket _ds;
		MulticastSocket _ms;
		UInt16 _defport;

		static bool comp_id (const IDMapping& p1, const IDMapping& p2);

		void onTimer( Timer& timer );

		/**
		 * This function acts as a wrapper for all the id-calculating functions
		 */
		void CalcId();

		/**
		 * Calculates between wich two id's is the biggest distance
		 * @param ida: After calling the function, this will be the biggest number
		 * @param idb: After calling the function, this will be the smaller number
		 */
		void biggestDifference( id_type &ida, id_type &idb );

		/**
		 * Calculates the middle id from 2 given ID's
		 * @param first: The highest ID
		 * @param second: The lowest ID
		 */
		id_type calcMiddleId( id_type first, id_type second );
};

#endif /* IDCOLLECTOR_H_ */
